import { IsString, IsOptional, IsNumber, Min, Max, IsArray, IsEmail, IsEnum } from 'class-validator';
import { Transform } from 'class-transformer';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';

// Organization DTOs
export class OrganizationDto {
  @ApiProperty({ description: 'Organization identifier' })
  id: string;

  @ApiProperty({ enum: ['organization'], description: 'Object type' })
  type: 'organization';

  @ApiProperty({ description: 'Organization name' })
  name: string;

  @ApiProperty({ description: 'Organization creation timestamp' })
  created_at: string;

  @ApiPropertyOptional({ description: 'Organization settings' })
  settings?: Record<string, any>;
}

export class UpdateOrganizationDto {
  @ApiPropertyOptional({ description: 'Organization name' })
  @IsOptional()
  @IsString()
  name?: string;

  @ApiPropertyOptional({ description: 'Organization settings' })
  @IsOptional()
  settings?: Record<string, any>;
}

// Member DTOs
export class MemberDto {
  @ApiProperty({ description: 'User identifier' })
  id: string;

  @ApiProperty({ enum: ['user'], description: 'Object type' })
  type: 'user';

  @ApiProperty({ description: 'User email' })
  email: string;

  @ApiProperty({ description: 'User full name' })
  name: string;

  @ApiProperty({ 
    enum: ['admin', 'member', 'viewer'], 
    description: 'User role in organization' 
  })
  role: 'admin' | 'member' | 'viewer';

  @ApiProperty({ description: 'User creation timestamp' })
  created_at: string;
}

export class UpdateMemberDto {
  @ApiProperty({ 
    enum: ['admin', 'member', 'viewer'],
    description: 'New role for the user'
  })
  @IsEnum(['admin', 'member', 'viewer'])
  role: 'admin' | 'member' | 'viewer';
}

export class MembersResponseDto {
  @ApiProperty({ type: [MemberDto], description: 'Array of member objects' })
  data: MemberDto[];

  @ApiProperty({ description: 'ID of the first member in the list', nullable: true })
  first_id: string | null;

  @ApiProperty({ description: 'ID of the last member in the list', nullable: true })
  last_id: string | null;

  @ApiProperty({ description: 'Whether there are more members available' })
  has_more: boolean;
}

// Invite DTOs
export class InviteDto {
  @ApiProperty({ description: 'Invite identifier' })
  id: string;

  @ApiProperty({ enum: ['invite'], description: 'Object type' })
  type: 'invite';

  @ApiProperty({ description: 'Invited email address' })
  email: string;

  @ApiProperty({ 
    enum: ['admin', 'member', 'viewer'], 
    description: 'Role to be assigned' 
  })
  role: 'admin' | 'member' | 'viewer';

  @ApiProperty({ 
    enum: ['pending', 'accepted', 'expired'], 
    description: 'Invite status' 
  })
  status: 'pending' | 'accepted' | 'expired';

  @ApiProperty({ description: 'Invite creation timestamp' })
  created_at: string;

  @ApiProperty({ description: 'Invite expiration timestamp' })
  expires_at: string;
}

export class CreateInviteDto {
  @ApiProperty({ description: 'Email address to invite' })
  @IsEmail()
  email: string;

  @ApiProperty({ 
    enum: ['admin', 'member', 'viewer'],
    description: 'Role to assign to the invited user'
  })
  @IsEnum(['admin', 'member', 'viewer'])
  role: 'admin' | 'member' | 'viewer';
}

export class InvitesResponseDto {
  @ApiProperty({ type: [InviteDto], description: 'Array of invite objects' })
  data: InviteDto[];

  @ApiProperty({ description: 'ID of the first invite in the list', nullable: true })
  first_id: string | null;

  @ApiProperty({ description: 'ID of the last invite in the list', nullable: true })
  last_id: string | null;

  @ApiProperty({ description: 'Whether there are more invites available' })
  has_more: boolean;
}

// API Key DTOs
export class ApiKeyDto {
  @ApiProperty({ description: 'API key identifier' })
  id: string;

  @ApiProperty({ enum: ['api_key'], description: 'Object type' })
  type: 'api_key';

  @ApiProperty({ description: 'API key name' })
  name: string;

  @ApiProperty({ description: 'Partial API key (masked)' })
  partial_key: string;

  @ApiProperty({ description: 'API key creation timestamp' })
  created_at: string;

  @ApiPropertyOptional({ description: 'Last used timestamp' })
  last_used_at?: string;

  @ApiProperty({ description: 'Whether the key is active' })
  is_active: boolean;
}

export class CreateApiKeyDto {
  @ApiProperty({ description: 'Name for the API key' })
  @IsString()
  name: string;
}

export class UpdateApiKeyDto {
  @ApiPropertyOptional({ description: 'New name for the API key' })
  @IsOptional()
  @IsString()
  name?: string;

  @ApiPropertyOptional({ description: 'Whether the key should be active' })
  @IsOptional()
  is_active?: boolean;
}

export class ApiKeysResponseDto {
  @ApiProperty({ type: [ApiKeyDto], description: 'Array of API key objects' })
  data: ApiKeyDto[];

  @ApiProperty({ description: 'ID of the first API key in the list', nullable: true })
  first_id: string | null;

  @ApiProperty({ description: 'ID of the last API key in the list', nullable: true })
  last_id: string | null;

  @ApiProperty({ description: 'Whether there are more API keys available' })
  has_more: boolean;
}

export class CreateApiKeyResponseDto extends ApiKeyDto {
  @ApiProperty({ description: 'The full API key (only shown once)' })
  key: string;
}

// Usage DTOs
export class UsageMetricsDto {
  @ApiProperty({ description: 'Usage date' })
  date: string;

  @ApiProperty({ description: 'Number of requests' })
  requests: number;

  @ApiProperty({ description: 'Total input tokens' })
  input_tokens: number;

  @ApiProperty({ description: 'Total output tokens' })
  output_tokens: number;

  @ApiProperty({ description: 'Total cost in USD' })
  cost_usd: number;
}

export class UsageResponseDto {
  @ApiProperty({ type: [UsageMetricsDto], description: 'Usage metrics by date' })
  data: UsageMetricsDto[];

  @ApiProperty({ description: 'Start date of the usage period' })
  start_date: string;

  @ApiProperty({ description: 'End date of the usage period' })
  end_date: string;

  @ApiProperty({ description: 'Total requests in the period' })
  total_requests: number;

  @ApiProperty({ description: 'Total input tokens in the period' })
  total_input_tokens: number;

  @ApiProperty({ description: 'Total output tokens in the period' })
  total_output_tokens: number;

  @ApiProperty({ description: 'Total cost in USD for the period' })
  total_cost_usd: number;
}

export class UsageQueryDto {
  @ApiPropertyOptional({ description: 'Start date (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  start_date?: string;

  @ApiPropertyOptional({ description: 'End date (YYYY-MM-DD)' })
  @IsOptional()
  @IsString()
  end_date?: string;

  @ApiPropertyOptional({ description: 'Granularity: day, week, month' })
  @IsOptional()
  @IsEnum(['day', 'week', 'month'])
  granularity?: 'day' | 'week' | 'month';
}

// Common Parameter DTOs
export class OrganizationParamsDto {
  @ApiProperty({ description: 'Organization identifier' })
  @IsString()
  organization_id: string;
}

export class UserParamsDto {
  @ApiProperty({ description: 'Organization identifier' })
  @IsString()
  organization_id: string;

  @ApiProperty({ description: 'User identifier' })
  @IsString()
  user_id: string;
}

export class InviteParamsDto {
  @ApiProperty({ description: 'Organization identifier' })
  @IsString()
  organization_id: string;

  @ApiProperty({ description: 'Invite identifier' })
  @IsString()
  invite_id: string;
}

export class ApiKeyParamsDto {
  @ApiProperty({ description: 'Organization identifier' })
  @IsString()
  organization_id: string;

  @ApiProperty({ description: 'API key identifier' })
  @IsString()
  api_key_id: string;
}

// List Query DTOs
export class AdminListQueryDto {
  @ApiPropertyOptional({ 
    description: 'Number of items to return', 
    minimum: 1, 
    maximum: 1000, 
    default: 20 
  })
  @IsOptional()
  @IsNumber()
  @Min(1)
  @Max(1000)
  @Transform(({ value }) => parseInt(value))
  limit?: number = 20;

  @ApiPropertyOptional({ 
    description: 'Cursor for pagination - return results before this ID' 
  })
  @IsOptional()
  @IsString()
  before_id?: string;

  @ApiPropertyOptional({ 
    description: 'Cursor for pagination - return results after this ID' 
  })
  @IsOptional()
  @IsString()
  after_id?: string;
}